package org.aman.publish.util;

import java.io.File;
import java.io.FileInputStream;
import java.util.*;

import org.aman.publish.Config;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.FileFileFilter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

public class SshFtpUtil {
    private static final Logger LOG = LoggerFactory.getLogger(SshFtpUtil.class);

    public static void main(String[] args) {
        File file = new File("D://36.txt");
        SshFtpUtil ft = new SshFtpUtil();
        Session s = ft.getSession(Config.Aman.getIp(), 22, Config.Aman.getPasswd(), Config.Aman.getPasswd());
        ChannelSftp sftp = ft.getSftpChannel(s);
        String upload = ft.uploadFile(sftp, "hot_Imgs", file);
        System.out.println(upload);
        ft.closeAll(sftp, s); //关闭连接
    }
    
    public ChannelSftp getSftpChannel(Session session) {
        Channel channel = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect();
            LOG.info("get Channel success!");
        } catch (JSchException e) {
            LOG.info("get Channel fail!", e);
        }
        return (ChannelSftp) channel;
    }

    public Session getSession(String host, int port, String username, final String password) {
        Session session = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(username, host, port);
            session.setPassword(password);
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            session.setConfig(sshConfig);
            session.connect();
            LOG.info("Session connected!");
        } catch (JSchException e) {
            LOG.info("get Channel failed!", e);
        }
        return session;
    }

    /**
     * 创建文件夹
     *
     * @param sftp
     * @param dir
     *            文件夹名称
     */
    public void mkdir(ChannelSftp sftp, String dir) {
        try {
            sftp.mkdir(dir);
            System.out.println("创建文件夹成功！");
        } catch (SftpException e) {
            System.out.println("创建文件夹失败！");
            e.printStackTrace();
        }
    }

    public void cdAndmkdirs(ChannelSftp sftp, String existDir, String[] dirs) {
        try {
            sftp.cd(existDir);
            for(String dir : dirs){
                try {
                    if(StringUtils.isNotBlank(dir)){
                        try {
                            sftp.cd(dir);
                        } catch (Exception e) {
                            sftp.mkdir(dir);
                            sftp.cd(dir);
                        }
                    }
                } catch (SftpException e) {
                    System.out.println("创建目录失败："+existDir+"/"+StringUtils.join(dirs, "/") + " at "+ dir);
                }
            }
        } catch (SftpException e) {
            System.out.println("创建文件夹失败！");
            e.printStackTrace();
        }
    }

    /**
     * @param sftp
     * @param dir
     *            上传目录
     * @param file
     *            上传文件
     * @return
     */
    public String uploadFile(ChannelSftp sftp, String dir, File file) {
        String result = "";
        try {
            sftp.cd(dir);
            
            if (file != null) {
                sftp.put(new FileInputStream(file), file.getName());
                result = "上传成功！";
            } else {
                result = "文件为空！不能上传！";
            }
        } catch (Exception e) {
            LOG.info("上传失败！", e);
            result = "上传失败！";
        }
        return result;
    }

    public String uploadDir(ChannelSftp sftp, String targetDir, File rootDir) {
        Collection<File> list = FileUtils.listFilesAndDirs(rootDir, FileFileFilter.FILE, DirectoryFileFilter.DIRECTORY);
        for(File file : list){
            try {
                if(file.isDirectory()){
                    String relativePath = file.getAbsolutePath().replace(rootDir.getAbsolutePath(), "").replaceAll("^(/|\\\\)", "");
                    String[] dirs = relativePath.split("/|\\\\");
                    cdAndmkdirs(sftp, targetDir, dirs);
                } else {
                    String relativePath = file.getParentFile().getAbsolutePath().replace(rootDir.getAbsolutePath(), "").replaceAll("^(/|\\\\)", "");
                    String[] dirs = relativePath.split("/|\\\\");
                    cdAndmkdirs(sftp, targetDir, dirs);
                    sftp.put(new FileInputStream(file), file.getName());
                    System.out.println("upload file: " + file.getAbsolutePath());
                }
            } catch (Exception e) {
                System.out.println("uploadFile失败:"+file.getAbsolutePath());
            }
        }
        return "";
    }
    

    /**
     * 下载文件
     *
     * @param directory
     *            下载目录
     * @param downloadFile
     *            下载的文件
     * @param saveFile
     *            存在本地的路径
     * @param sftp
     */
    public String download(String directory, String downloadFile,
                           String saveFile, ChannelSftp sftp) {
        String result = "";
        try {
            sftp.cd(directory);
            sftp.get(downloadFile, saveFile);
            result = "下载成功！";
        } catch (Exception e) {
            result = "下载失败！";
            LOG.info("下载失败！", e);
            ;
        }
        return result;
    }

    /**
     * 删除文件
     *
     * @param directory
     *            要删除文件所在目录
     * @param deleteFile
     *            要删除的文件
     * @param sftp
     */
    public String delete(String directory, String deleteFile, ChannelSftp sftp) {
        String result = "";
        try {
            sftp.cd(directory);
            sftp.rm(deleteFile);
            result = "删除成功！";
        } catch (Exception e) {
            result = "删除失败！";
            LOG.info("删除失败！", e);
        }
        return result;
    }

    public void deleteDir(ChannelSftp sftp, String targetPath) {
        try {
            sftp.cd(targetPath);
            Vector list = sftp.ls(targetPath);
            for(Object o : list){
                ChannelSftp.LsEntry e = (ChannelSftp.LsEntry) o;
                if(".".equals(e.getFilename()) || "..".equals(e.getFilename())){
                    continue;
                }
                if(e.getLongname().startsWith("d")){
                    deleteDir(sftp, targetPath + "/" + e.getFilename());
                    sftp.cd(targetPath);
                    sftp.rmdir(e.getFilename());
                    System.out.println("delete dir: "+targetPath+"/"+e.getFilename());
                } else {
                    sftp.rm(e.getFilename());
                    System.out.println("delete file: "+targetPath+"/"+e.getFilename());
                }
            }
        } catch (SftpException e) {
            e.printStackTrace();
        }
    }
    

    private void closeChannel(Channel channel) {
        if (channel != null) {
            if (channel.isConnected()) {
                channel.disconnect();
            }
        }
    }

    private void closeSession(Session session) {
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }

    public void closeAll(ChannelSftp sftp, Session session) {
        try {
            closeChannel(sftp);
            closeSession(session);
        } catch (Exception e) {
            LOG.info("closeAll", e);
        }
    }


}